package com.xiaoshuidi.cloud.module.iot.dal.repository;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.DeviceListByNosApiReqVO;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.PullDeviceApiVo;
import com.xiaoshuidi.cloud.module.iot.controller.admin.doorlock.vo.DeviceListByNosReqVO;
import com.xiaoshuidi.cloud.module.iot.controller.admin.doorlock.vo.PullDeviceVo;
import com.xiaoshuidi.cloud.module.iot.dal.mapper.DeviceDoMapper;
import com.xiaoshuidi.cloud.module.iot.dal.model.watermeter.WaterMeterCommonRequestModel;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.WaterMeterCommonResponseModel;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDo;
import com.xiaoshuidi.cloud.module.iot.enums.DeviceTypeEnum;
import com.xiaoshuidi.cloud.module.rooms.vo.RoomSdiotWaringVo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @Author Feng
 * @date 2023/6/16
 */
@Component
public class DeviceRepository extends ServiceImpl<DeviceDoMapper, TbDeviceDo> {

    @Autowired
    private DeviceDoMapper deviceDoMapper;
    /**
     * 据水滴api_no列表拉取设备列表
     *
     * @param apiNos
     * @return
     */
    public List<PullDeviceVo> getDeviceListByApiNo(List<String> apiNos) {
        return this.baseMapper.getDeviceListByApiNo(apiNos);
    }


    /**
     * 批量删除设备
     *
     * @param deletedDeviceList
     * @return
     */
    public int deleteDeviceList(List<TbDeviceDo> deletedDeviceList) {
        return this.baseMapper.deleteDeviceList(deletedDeviceList);
    }

    /**
     * 根据device_name模糊查询设备列表（品类）
     *
     * @param tbDeviceDo
     * @return
     */
    public List<PullDeviceVo> getDevcieListByDeviceName(TbDeviceDo tbDeviceDo) {
        QueryWrapper<TbDeviceDo> wrapper = Wrappers.query();
        wrapper.eq("status", 1)
                .eq(StrUtil.isNotEmpty(tbDeviceDo.getDeviceType()), "device_type", tbDeviceDo.getDeviceType())
                .like(StrUtil.isNotEmpty(tbDeviceDo.getDeviceName()), "device_name", tbDeviceDo.getDeviceName());
        return this.baseMapper.getDevcieListByDeviceName(wrapper);
    }


    /**
     * 根据device_no 列表批量查询设备列表
     *
     * @param deviceListByNosReqVO
     * @return
     */
    public List<PullDeviceVo> getDeviceListByDeviceNos(@Param("deviceListByNosReqVO") DeviceListByNosReqVO deviceListByNosReqVO) {
        QueryWrapper<TbDeviceDo> wrapper = Wrappers.query();
        wrapper.eq("status", 1)
                .in(CollectionUtil.isNotEmpty(deviceListByNosReqVO.getDeviceNos()), "device_no", deviceListByNosReqVO.getDeviceNos());
        return this.baseMapper.getDeviceListByDeviceNos(wrapper);
    }

    /**
     * 批量清零设备剩余金额
     *
     * @param deviceNos
     * @return
     */
    public int updateRemainingAmountClear(List<String> deviceNos) {
        return this.baseMapper.updateRemainingAmountClear(deviceNos);
    }

    /**
     * 根据device_no 列表批量分页查询设备列表
     *
     * @param deviceListByNosReqVO
     * @return
     */
    public PageInfo<PullDeviceApiVo> findDeviceListByDeviceNosPage(DeviceListByNosApiReqVO deviceListByNosReqVO) {
        PageInfo<PullDeviceApiVo> pageInfo = new PageInfo<>();
        QueryWrapper<TbDeviceDo> wrapper = Wrappers.query();
        wrapper.eq("status", 1)
                .eq(deviceListByNosReqVO.getOnlineStatus() != null, "online_status", deviceListByNosReqVO.getOnlineStatus())
                .and(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && "watermeter".equals(deviceListByNosReqVO.getDeviceType()),
                        s -> s.eq("device_type", "hot_watermeter")
                                .or()
                                .eq("device_type", "cold_watermeter"))
                .eq(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && !"watermeter".equals(deviceListByNosReqVO.getDeviceType())
                        , "device_type", deviceListByNosReqVO.getDeviceType())
                .ge(deviceListByNosReqVO.getPowerStatus() != null && deviceListByNosReqVO.getPowerStatus().equals(1), "battery_level", 10)
                .lt(deviceListByNosReqVO.getPowerStatus() != null && !deviceListByNosReqVO.getPowerStatus().equals(1), "battery_level", 10)
                .in(CollectionUtil.isNotEmpty(deviceListByNosReqVO.getDeviceNos()), "device_no", deviceListByNosReqVO.getDeviceNos());
        List<PullDeviceApiVo> pullDeviceVos = this.baseMapper.findDeviceListByDeviceNosPage(wrapper);
        pageInfo.setTotal(pullDeviceVos.size());
        pageInfo.setList(pullDeviceVos);
        return pageInfo;
    }

    /**
     * 根据device_no 列表批量查询设备列表
     *
     * @param deviceListByNosReqVO
     * @return
     */
    public List<PullDeviceVo> findDeviceListByDeviceNos(DeviceListByNosReqVO deviceListByNosReqVO) {
        QueryWrapper<TbDeviceDo> wrapper = Wrappers.query();
        wrapper.eq("status", 1)
                .eq(deviceListByNosReqVO.getOnlineStatus() != null, "online_status", deviceListByNosReqVO.getOnlineStatus())
                .and(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && "watermeter".equals(deviceListByNosReqVO.getDeviceType()),
                        s -> s.eq("device_type", "hot_watermeter")
                                .or()
                                .eq("device_type", "cold_watermeter"))
                .eq(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && !"watermeter".equals(deviceListByNosReqVO.getDeviceType())
                        , "device_type", deviceListByNosReqVO.getDeviceType())
                .ge(deviceListByNosReqVO.getPowerStatus() != null && deviceListByNosReqVO.getPowerStatus().equals(1), "battery_level", 10)
                .lt(deviceListByNosReqVO.getPowerStatus() != null && !deviceListByNosReqVO.getPowerStatus().equals(1), "battery_level", 10)
                .in(CollectionUtil.isNotEmpty(deviceListByNosReqVO.getDeviceNos()), "device_no", deviceListByNosReqVO.getDeviceNos());
        List<PullDeviceVo> pullDeviceVos = baseMapper.findDeviceListByDeviceNos(wrapper);
        return pullDeviceVos;
    }

    public List<TbDeviceDo> getDeviceListByOneApiNo(String apiNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getApiNo, apiNo).eq(TbDeviceDo::getStatus, 1);
        return this.list(wrapper);
    }

    public TbDeviceDo getDeviceByDeviceNo(String deviceNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceNo).eq(TbDeviceDo::getStatus, 1);
        TbDeviceDo tbDeviceDo = this.getOne(wrapper);
        return tbDeviceDo;
    }

    public TbDeviceDo getDeviceByDeviceThirdNo(String deviceThirdNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceThirdNo, deviceThirdNo).eq(TbDeviceDo::getStatus, 1);
        TbDeviceDo tbDeviceDo = this.getOne(wrapper);
        return tbDeviceDo;
    }
    public WaterMeterCommonResponseModel getWatermeterInfoBydeviceNo(WaterMeterCommonRequestModel waterMeterCommonRequestModel) {
        WaterMeterCommonResponseModel waterMeterCommonResponseModel = this.baseMapper.getWatermeterInfoBydeviceNo(waterMeterCommonRequestModel.getDeviceNo());
        return waterMeterCommonResponseModel;
    }


    /**
     * 根据设备no查询设备
     *
     * @param deviceNo
     * @return
     */
    public TbDeviceDo getWatermeterInfoByDeviceNo(String deviceNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceNo)
                .in(TbDeviceDo::getDeviceType, Arrays.asList(DeviceTypeEnum.COLD_WATERMETE_TYPE_ENUM.getCode(), DeviceTypeEnum.HOT_WATERMETE_TYPE_ENUM.getCode()))
                .eq(TbDeviceDo::getStatus, 1);
        TbDeviceDo tbDeviceDo = this.getOne(wrapper);
        return tbDeviceDo;
    }


    /**
     * 手动刷新-更改设备当前读数，在线离线，通断电，上报时间等 (含版本控制)
     *
     * @param currentDevice
     * @return
     */
    public boolean updateTbDeviceRecordAndVersion(TbDeviceDo currentDevice) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, currentDevice.getDeviceNo())
                .eq(TbDeviceDo::getBrandNo, currentDevice.getBrandNo())
                .eq(TbDeviceDo::getVersion, currentDevice.getVersion());
        return this.update(currentDevice, wrapper);
    }

    public TbDeviceDo getAmmeterInfoByDeviceNo(String deviceNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceNo)
                .eq(TbDeviceDo::getDeviceType, DeviceTypeEnum.AMMETER.getCode())
                .eq(TbDeviceDo::getStatus, 1);
        TbDeviceDo tbDeviceDo = this.getOne(wrapper);
        return tbDeviceDo;
    }

    /**
     * 修改电表当前合闸拉闸状态
     *
     * @param deviceNo
     * @param onoff
     * @return
     */
    public boolean updateAmmeterSwitchOnoff(String deviceNo, int onoff) {
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setPowerStatus(onoff);
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceNo)
                .eq(TbDeviceDo::getStatus, 1);
        return update(tbDeviceDo, wrapper);

    }

    /**
     * 根据条件查询tb_device记录
     *
     * @param tbDeviceDo
     * @return
     */
    public TbDeviceDo getTbDeviceByConditon(TbDeviceDo tbDeviceDo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceThirdNo, tbDeviceDo.getDeviceThirdNo())
                .eq(TbDeviceDo::getBrandNo, tbDeviceDo.getBrandNo())
                .eq(TbDeviceDo::getStatus, 1);
        return getOne(wrapper);
    }


    /**
     * 根据deviceName和brandNo查询tb_device记录
     *
     * @param deviceName
     * @param brandNo
     * @return
     */
    public TbDeviceDo getTbDeviceByDeviceNameAndBrandNo(String deviceName, String brandNo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceName, deviceName)
                .eq(TbDeviceDo::getBrandNo, brandNo)
                .eq(TbDeviceDo::getStatus, 1);
        return getOne(wrapper);
    }

    public boolean updateWaterMeterSwitchOnoff(String deviceNo, int status) {
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        tbDeviceDo.setPowerStatus(status);
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceNo)
                .eq(TbDeviceDo::getStatus, 1);
        return update(tbDeviceDo, wrapper);

    }
    public boolean updateDeviceDoByThirdId(String deviceThirdNo) {
        TbDeviceDo tbDeviceDo = new TbDeviceDo();
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, deviceThirdNo);
        return update(tbDeviceDo, wrapper);

    }
    public Boolean tianchengUpdateOnlineStatus(TbDeviceDo tbDeviceDo){
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        tbDeviceDo.setReportTime(LocalDateTime.now());
        tbDeviceDo.setUpdateTime(LocalDateTime.now());
        wrapper.eq(TbDeviceDo::getDeviceNo, tbDeviceDo.getDeviceThirdNo());
        return update(tbDeviceDo, wrapper);
    }

    /*
     * @description:门锁电量处理
     * @author: James
     * @date: 2023/9/18 16:30
     * @param: [deviceNo, status]
     * @return: boolean
     **/
    public boolean updateTbDeviceRecord(TbDeviceDo tbDeviceDo) {
        LambdaQueryWrapper<TbDeviceDo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TbDeviceDo::getDeviceNo, tbDeviceDo.getDeviceNo())
                .eq(TbDeviceDo::getStatus, 1);
        return update(tbDeviceDo, wrapper);

    }

    public List<PullDeviceApiVo> findDeviceList(DeviceListByNosApiReqVO deviceListByNosReqVO) {
        QueryWrapper<TbDeviceDo> wrapper = Wrappers.query();
        wrapper.eq("status", 1)
                .eq(deviceListByNosReqVO.getOnlineStatus() != null, "online_status", deviceListByNosReqVO.getOnlineStatus())
                .eq(deviceListByNosReqVO.getPowerStatus() != null, "power_status", deviceListByNosReqVO.getPowerStatus())
                .and(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && "watermeter".equals(deviceListByNosReqVO.getDeviceType()),
                        s -> s.eq("device_type", "hot_watermeter")
                                .or()
                                .eq("device_type", "cold_watermeter"))
                .eq(StrUtil.isNotEmpty(deviceListByNosReqVO.getDeviceType()) && !"watermeter".equals(deviceListByNosReqVO.getDeviceType())
                        , "device_type", deviceListByNosReqVO.getDeviceType());
//                .like(StringUtils.isNotEmpty(deviceListByNosReqVO.getDeviceNo()), "device_no", deviceListByNosReqVO.getDeviceNo());
        if (ObjectUtils.isNotEmpty(deviceListByNosReqVO.getPowerLeve())) {
            if (deviceListByNosReqVO.getPowerLeve() == 1) {
                wrapper.le("battery_level", 10);
            } else if (deviceListByNosReqVO.getPowerLeve() == 2) {
                wrapper.le("battery_level", 20);
            } else if (deviceListByNosReqVO.getPowerLeve() == 3) {
                wrapper.le("battery_level", 50)
                        .gt("battery_level", 20);
            } else if (deviceListByNosReqVO.getPowerLeve() == 4) {
                wrapper.le("battery_level", 80)
                        .gt("battery_level", 50);
            } else if (deviceListByNosReqVO.getPowerLeve() == 5) {
                wrapper.le("battery_level", 100)
                        .gt("battery_level", 80);
            }
        }
        List<PullDeviceApiVo> pullDeviceVos = this.baseMapper.findDeviceListByDeviceNosPage(wrapper);
        return pullDeviceVos;
    }
    public int updateByIndex(TbDeviceDo tbDeviceDo) {
        return deviceDoMapper.updateByIndex(tbDeviceDo);
    }

}
